
#include "messageCenter.h"
#include "message.hpp"

using namespace std;

std::mutex MessageCenter::m_mutex;
MessageCenter *MessageCenter::m_instance = nullptr;
MessageCenter *MessageCenter::getInstance()
{
    if (m_instance == nullptr)
    {
        m_mutex.lock();
        if (m_instance == nullptr)
        {
            m_instance = new MessageCenter();
        }
        m_mutex.unlock();
    }
    return m_instance;
}

MessageCenter::MessageCenter() : m_isMsgThreadRunning(true)
{
    m_msgThread = new thread(&MessageCenter::messageQueueThread, this);
    m_msgThread->detach();
}

MessageCenter::~MessageCenter()
{
    m_isMsgThreadRunning = false;
    if (m_instance != nullptr)
    {
        delete m_instance;
        m_instance = nullptr;
    }
}

void MessageCenter::attach(IHandle *pHandle)
{
    RETURN_IF(!pHandle);

    string t = pHandle->getType();

    m_handleMutex.lock();
    Handles *p = m_handles[t];
    // 消息绑定的接收者列表不存在添加一个列表
    if (p == nullptr)
    {
        p = new Handles;
        p->push_back(pHandle);
        m_handles[t] = p;
    }
    // 接收者列表存在直接插入
    else
    {
        for (Handles::iterator it = p->begin(); it != p->end(); ++it)
        {
            // 存在直接返回，防止重复插入
            if (*it == pHandle)
            {
                break;
            }
            p->push_back(pHandle);
        }
    }
    m_handleMutex.unlock();
}

void MessageCenter::detach(IHandle *pHandle)
{
    RETURN_IF(!pHandle);

    m_handleMutex.lock();
    string t = pHandle->getType();
    Handles *p = m_handles[t];
    if (p != nullptr)
    {
        for (Handles::iterator it = p->begin(); it != p->end(); ++it)
        {
            if (*it == pHandle)
            {
                // 只从列表中移除，不删除，删除会重复释放内存导致 SendMsg 中崩溃
                auto h = *it;
                p->remove(h);
                break;
            }
        }
    }
    m_handleMutex.unlock();
}

bool MessageCenter::sendMsg(const IMessage *pMsg)
{
    if (pMsg == nullptr)
        return false;

    string t = typeid(*pMsg).name();
    m_handleMutex.lock();
    Handles *p = m_handles[t];
    if (p != nullptr)
    {
        for (Handles::iterator it = p->begin(); it != p->end(); ++it)
        {
            IHandle *hanle = *it;
            if (!pMsg->send(hanle))
                break;
        }
    }
    m_handleMutex.unlock();
    return true;
}

void MessageCenter::pushMessgae(IMessage *pMsg, MessagePriority priority)
{
    {
        lock_guard<mutex> locker(m_msgMutex);
        if (pMsg == nullptr)
            return;
        switch (priority)
        {
        case MessagePriority::MP_COMMON:
            m_msgList.push_back(pMsg);
            break;
        case MessagePriority::MP_EMERGENCY:
            m_msgList.push_front(pMsg);
            break;
        default:
            m_msgList.push_back(pMsg);
            break;
        }
    }
    m_cv.notify_one();
}

void MessageCenter::messageQueueThread()
{
    while (m_isMsgThreadRunning)
    {
        IMessage *pMsg = nullptr;
        {
            unique_lock<mutex> locker(m_msgMutex);
            if (m_msgList.empty())
            {
                // 当前队列为空，等待唤醒
                m_cv.wait(locker);
            }
        }
        {
            lock_guard<mutex> locker(m_msgMutex);
            // 从队列开头取出一个数据（不在消息队列中加锁，否则消息压入会受到影响）
            pMsg = m_msgList.front();
            m_msgList.pop_front();
        }

        string t = typeid(*pMsg).name();
        m_handleMutex.lock();
        Handles *p = m_handles[t];
        if (p != nullptr)
        {
            for (Handles::iterator it = p->begin(); it != p->end(); ++it)
            {
                IHandle *hanle = *it;
                pMsg->send(hanle);
            }
        }
        m_handleMutex.unlock();
        delete pMsg;
        pMsg = nullptr;
    }
}